//映射关系类，绑定key与事件方法的映射关系，还用于触发ui更新

import { Msg } from "../../util/msg";
import { Singleton } from "../../util/Singleton";
import { Save } from "../../util/save";
import { Level } from "../../logic/level/level";


export class Bind extends Singleton {

    // Event dictionary, used to construct the mapping of keys to events.
    _map: { [name: string]: Function } = {}

    // Total number of events.
    totalEvents = 0;

    public init (): void {

        // Registered events are used to count the total number of events.
        Msg.on('msg_count_events', this.countEvents.bind(this));

        //注册用于测试的按钮事件
        Msg.on('btn_start_test', this.countEvents.bind(this));

        //下面是一些测试用的映射关系，实际项目中可以根据自己的需求添加
        
        //绑定映射关系，key名为节点名，value为事件方法
        this._map['btn_start_test'] = () => {
            Msg.emit('btn_start_test');
        }
        //绑定游戏击杀次数
        this._map['txt_killed'] = () => Save.Instance.getStatistics('killedTimes');

        //绑定游戏分数（节点名txt_score与数据_gameScore）
        this._map['txt_score'] = () => `${Level.Instance._gameScore.toFixed(2)}`;
        //绑定游戏生命
        this._map['txt_hp'] = () => `${Level.Instance._hp}`;
     

    }

    /**
     * The method is used to initialize the event binder.
     * @param data The data is game events mapping.
     */
    public initData (data: [{ name: string, event: string, data: string | undefined }]) {

        this.init();

        data.forEach(events => {
            let name = events.name;
            let event = events.event;
            let data = events.data;
            if (!events.data) data = undefined;
            this._map[name] = () => {
                Msg.emit(event, data);
            }
        });
    }

    /**
     * This method is used to execute specific events by key.
     * @param key The name of the event to execute.
     */
    //根据映射关系名，获取对应的事件并执行，并且触发ui的更新
    public on (key: string) {
        var event = this._map[key];
        if (event) {
            event();
            this.countEvents();
        } else {
            console.warn('Can not find key:' + key);
        }
    }

    /**
     * This method is to get this event and return the result of executing the method.
     * @param key The key is event to execute.
     * @returns 
     */
    //根据映射关系名，获取对应的事件返回值
    public get (key: string) {
        return this._map[key]();
    }

    /**
     * This method is used to determine if the event is mapped or not.
     * @param key The key of the event to be judged.
     * @returns 
     */
    public hasBind (key: string): boolean {
        return this._map[key] !== undefined;
    }

    /**
     * Current frame event execution statistics.
     */
    public countEvents () {
        this.totalEvents++;
    }

    /**
     * Check if the count needs to be refreshed according to the current frame.
     */
    //根据当前帧的事件执行统计，判断是否需要刷新ui
    public checkRefresh () {
        if (this.totalEvents > 0) {
            Msg.emit("refresh_ui");
            this.totalEvents = 0;
        }
    }

    /**
     * This method is an update function for each frame.
     * @param deltaTime This value is the execution time per frame.
     */
    public update (deltaTime: number): void {

        // Check if a refresh is needed.
        this.checkRefresh();
    }

}